#
# InitPvcsCustomMenu.py
#
# this class implements the functionality to add automatically
# a custom menu to SNiFF+, if the executable 'vcs' is in the path
#
# Author: Uwe Stieber
# Copyright (c) 1998, 1999 TakeFive Software, Salzburg
#

# where should we write the menu
#forceUserLevel = 0		# ... write to $SNIFF_DIR/config/SiteMenus.sniff
forceUserLevel = 1			# ... write to $SNIFF_DIR/Profile/<username>/UserMenus.sniff
							# 	  or $SNIFF_RESOURCE_DIR/UserMenus.sniff
# enable automatic menu level merge
#enableAutoMenu = 0			# ... NO automatic menu merge
enableAutoMenu = 1			# ... automatic menu merge will be processed

# force overriding of newer UserMenus.sniff
forceMenu = 0				# check the modification times against UserMenu.sniff
							# and recreate UserMenus.sniff only if SiteMenus.sniff
							# or PvcsMenus.sniff is newer than UserMenus.sniff
#forceMenu = 1				# create every time UserMenus.sniff
 
### DON'T change anything below this line !!!!!

# some system modules
import sys
import os
import string
from stat import *

# debug variable
TEST = 0
if os.environ.has_key("PVCSDEBUG"):
	TEST = 1

# import some SNiFF+ modules
from vcs import is_readable, is_writable, is_reachable, chmod

# append PVCS module path to common search path
import searchPathLib
searchPathLib.extendModulePath('lib/python/Sniff/Pvcs')

import PVCSConstants

# global used variables
sniff_dir = ""
location = ""
templateFile = ""

def doPreChecks():
	if TEST: print "(PVCS Custom Menu)@B@g>>>@x doPreChecks@B"
	global sniff_dir, location, templateFile
	# we need to known, where SNIFF_DIR is
	if os.environ.has_key("SNIFF_DIR"):
		sniff_dir = os.environ["SNIFF_DIR"]
	else:
		print "(PVCS Custom Menu)@BInformation:@B environment variable @BSNIFF_DIR@B not found ! Stop processing !"
		if TEST: print "(PVCS Custom Menu)@B@r<<<@x doPreChecks@B"
		return -1
	# find location, where to write
	if forceUserLevel:
		# try to write to UserMenus.sniff
		location = os.path.join(searchPathLib.getUsersProfileDir(), "UserMenus.sniff")
	else:
		# try to write to SiteMenus.sniff
		location = os.path.join(sniff_dir, "config", "SiteMenus.sniff")
	if TEST:
		print "(PVCS Custom Menu)menu location: @B@b%s@x@B" % location
	templateFile = os.path.join(sniff_dir, "config", "PvcsMenu.sniff")
	if TEST:
		print "(PVCS Custom Menu)templateFile: @B@b%s@x@B" % templateFile
	# check modification time
	if is_readable(os.path.join(sniff_dir, "config", "SiteMenus.sniff")):
		siteMenusMTIME = os.stat(os.path.join(sniff_dir, "config", "SiteMenus.sniff"))[ST_MTIME]
	else:
		siteMenusMTIME = 0
	if is_readable(location):
		userMenusMTIME = os.stat(location)[ST_MTIME]
	else:
		userMenusMTIME = 0
	if is_readable(templateFile):
		pvcsMenusMTIME = os.stat(templateFile)[ST_MTIME]
	else:
		pvcsMenusMTIME = 0
	if userMenusMTIME >= siteMenusMTIME and userMenusMTIME >= pvcsMenusMTIME:
		if forceMenu == 0:
			if TEST: print "(PVCS Custom Menu)@B@r<<<@x doPreChecks (menus file is up-to-date)@B"
			return -1
		else:
			if TEST: print "(PVCS Custom Menu)@B@r\tforce writing of %s !!@x@B" % location
	if TEST: print "(PVCS Custom Menu)@B@r<<<@x doPreChecks@B"
	return 0

# is the executable in the path ?
if not is_reachable("vcs"):
	enableAutoMenu = 0

# main control function to build the custom menu
def buildPVCSCustomMenu():
	if TEST: print "(PVCS Custom Menu)@B@g>>>@x buildPVCSCustomMenu@B"
	# at first, check the 'template' file $SNIFF_DIR/config/PvcsMenu.sniff
	# exists
	if os.path.isfile(templateFile) and is_readable(templateFile):
		# ok, file exists
		if TEST:
			print "(PVCS Custom Menu)\tFile '@B%s@B' exists and is readable !" % templateFile
		if forceUserLevel:
			processUserLevel()
		else:
			processSiteLevel()
	else:
		# file doesnt exists
		if TEST:
			print "(PVCS Custom Menu)\tFile '@B%s@B' doesn't exists or isn't readable !" % templateFile
	if TEST: print "(PVCS Custom Menu)@B@r<<<@x buildPVCSCustomMenu@B"
	return

# process SiteMenus.sniff
def processSiteLevel():
	if TEST: print "(PVCS Custom Menu)@B@g>>>@x processSiteLevel@B"
	if os.path.isfile(location):
		# SiteMenus.sniff exists
		# in this case, the file must be writeable
		if is_writable(location):
			# ok, is writeable
			# process operations
			deletePvcsMenu()
			appendPvcsMenu()
		else:
			# it isn't writeable
			print "(PVCS Custom Menu) File @B%s@B isn't writeable ! Stop processing !" % location
	else:
		# SiteMenus.sniff doesn't exists
		# create file
		try:
			menuFile = open(location, "a")
			menuFile.close()
		except IOError:
			print "(PVCS Custom Menu) Cannot create @B%s@B ! Stop processing !" % location
			if TEST: print "(PVCS Custom Menu)@B@r<<<@x processSiteLevel@B"
			return		
		# process operations
		appendPvcsMenu()
	if TEST: print "(PVCS Custom Menu)@B@r<<<@x processSiteLevel@B"
	return

# process UserMenus.sniff
def processUserLevel():
	if TEST: print "(PVCS Custom Menu)@B@g>>>@x processUserLevel@B"
	if os.path.isfile(location):
		# UserMenus.sniff exists
		# in this case, the file must be writeable
		if is_writable(location):
			# ok, is writeable
			# process operations
			mergeSiteLevel()
			deletePvcsMenu()
			appendPvcsMenu()
		else:
			# it isn't writeable
			print "(PVCS Custom Menu) File @B%s@B isn't writeable ! Stop processing !" % location
	else:
		# UserMenus.sniff doesn't exists
		# create file
		try:
			menuFile = open(location, "a")
			menuFile.close()
		except IOError:
			print "(PVCS Custom Menu) Cannot create @B%s@B ! Stop processing !" % location
			if TEST: print "(PVCS Custom Menu)@B@r<<<@x processUserLevel@B"
			return		
		# process operations
		mergeSiteLevel()
		appendPvcsMenu()
	if TEST: print "(PVCS Custom Menu)@B@r<<<@x processUserLevel@B"
	return

# merge SiteLevel menus to UserLevel
def mergeSiteLevel():
	if TEST: print "(PVCS Custom Menu)@B@g>>>@x mergeSiteLevel@B"
	try:
		menuFile = open(location, "r")
		tempFileName = PVCSConstants.getTempFile()
		if TEST: print "(PVCS Custom Menu)\ttempFileName: '@B%s@B'" % tempFileName
		tempFile = open(tempFileName, "w")
		siteFile = open(os.path.join(sniff_dir, "config", "SiteMenus.sniff"), "r")
	except IOError:
		if TEST: print "(PVCS Custom Menu)@B@r<<<@x mergeSiteLevel (IOError)@B"
		return
	# read the non-comment lines and store the lines in a list
	siteFileLines = []
	origSiteFileLines = []
	uniqueMakerTool = 0
	uniqueMakerSeperator = 0
	for aSiteFileLine in siteFile.readlines():
		if string.lstrip(aSiteFileLine) != "":
			origSiteFileLines.append(aSiteFileLine)
			if len(aSiteFileLine) > 0 and aSiteFileLine[0] == '^':
				aSiteFileLine = "%d__%s" % (uniqueMakerTool, aSiteFileLine)
				uniqueMakerTool = uniqueMakerTool + 1
			if len(aSiteFileLine) > 0 and aSiteFileLine[0] == '-':
				aSiteFileLine = "%d__%s" % (uniqueMakerSeperator, aSiteFileLine)
				uniqueMakerSeperator = uniqueMakerSeperator + 1
			siteFileLines.append(aSiteFileLine)
	siteFileLines.append("### automatic merged Site Level menus START ###\n")
	siteFileLines.append("### automatic merged Site Level menus END ###\n")
	if TEST:
		print "(PVCS Custom Menu)@BsiteFile line list: @b",
		print siteFileLines,
		print "@x@B"
	# read the UserMenus File
	lastLine = ""
	uniqueMakerTool = 0
	uniqueMakerSeperator = 0
	siteMenusMode = 0
	if TEST:
		print "(PVCS Custom Menu)@Bstart removing SiteMenus lines from UserMenus@B"
	for aUserFileLine in menuFile.readlines():
		# copy only lines which ar not empty and not in SiteMenus.sniff
		# NOTE: also comment lines from SiteMenus.sniff will deleted
		if siteMenusMode == 0:
			if string.strip(aUserFileLine) == "### automatic merged Site Level menus START ###":
				siteMenusMode = 1
		else:
			if string.strip(aUserFileLine) == "### automatic merged Site Level menus END ###":
				siteMenusMode = 0
				continue
		
		# process the line only if we are not in siteMenusMode	
		if siteMenusMode == 0:
			if string.lstrip(aUserFileLine) != lastLine:
				if TEST:
					print "(PVCS Custom Menu)@B\twrite line !"
				# write to temporary file
				tempFile.write(aUserFileLine)
				# save to lastLine
				lastLine = string.lstrip(aUserFileLine)
				continue

		# do the following check to avoid to much empty lines
		if TEST:
			print "(PVCS Custom Menu)@Bcurrent UserMenus line: @b'%s'@x@B" % aUserFileLine
		if string.lstrip(aUserFileLine) != lastLine:
			# check, if it is a Site Level Line
			aUserFileLineTemp = ""
			if len(aUserFileLine) > 0 and aUserFileLine[0] == '^':
				aUserFileLineTemp = "%d__%s" % (uniqueMakerTool, aUserFileLine)
				uniqueMakerTool = uniqueMakerTool + 1
			if len(aUserFileLine) > 0 and aUserFileLine[0] == '-':
				aUserFileLineTemp = "%d__%s" % (uniqueMakerSeperator, aUserFileLine)
				uniqueMakerSeperator = uniqueMakerSeperator + 1
			if aUserFileLine not in siteFileLines:
				if aUserFileLine[0] == '^' or aUserFileLine[0] == '-':
					if TEST:
						print "(PVCS Custom Menu)@BaUserFileLineTemp: @b'%s'@x@B" % aUserFileLineTemp
					if len(aUserFileLineTemp) > 0 and aUserFileLineTemp not in siteFileLines:
						if TEST:
							print "(PVCS Custom Menu)@B\twrite line !@B"
						# write to temporary file
						tempFile.write(aUserFileLine)
						# save to lastLine
						lastLine = string.lstrip(aUserFileLine)
					else:
						if TEST:
							print "(PVCS Custom Menu)@B\tskip line ! (in siteFileLines)@B"
				else:
					if TEST:
						print "(PVCS Custom Menu)@B\twrite line !@B"
					# write to temporary file
					tempFile.write(aUserFileLine)
					# save to lastLine
					lastLine = string.lstrip(aUserFileLine)
			else:
				if TEST:
					print "(PVCS Custom Menu)@B\tskip line ! (in siteFileLines)@B"
		else:
			if TEST:
				print "(PVCS Custom Menu)@B\tskip line ! (is equal to lastLine)"
	# copy all non comment SiteLevel lines to temporary file
	tempFile.write("\n### automatic merged Site Level menus START ###\n")
	if TEST:
		print "(PVCS Custom Menu)@Bstart merging SiteMenus lines to UserMenus@B"
	for aSiteFileLine in origSiteFileLines:
		if TEST:
			print "(PVCS Custom Menu)@Bcurrent SiteMenus line: @b'%s'@x@B" % aSiteFileLine
		if string.lstrip(aSiteFileLine)[0] != '#':
			# seperate tools witch a empty line
			if string.lstrip(aSiteFileLine)[0] == '^':
				tempFile.write("\n")
				if TEST:
					print "(PVCS Custom Menu)@B\tit's a tool declaration file@B"
			tempFile.write(aSiteFileLine)
			if TEST:
				print "(PVCS Custom Menu)@B\twrite Line !@B"
		else:
			if TEST:
				print "(PVCS Custom Menu)@B\tskip line ! (its a comment Line)@B"

	tempFile.write("\n### automatic merged Site Level menus END ###\n")
	# close all file
	menuFile.close()
	tempFile.close()
	siteFile.close()
	# remove old file
	try:
		if sys.platform == "win32":
			chmod(location, 'ug+w')
		os.remove(location)
		# rename temp file
		if sys.platform == "win32":
			try:
				os.rename(tempFileName, location)
			except:
				# renaming failed
				print "Renaming from @B%s@B to @B%s@B failed ! Perform renaming manually to make the PVCS integration menus available !" % (tempFileName, location)
		else:
			try:
				menuFile = open(location, "w")
				tempFile = open(tempFileName, "r")
				menuFile.writelines(tempFile.readlines())
				tempFile.close()
				menuFile.close()
				os.remove(tempFileName)
			except os.error, exc:
				if TEST: print "(PVCS Custom Menu)@B@r<<<@x mergeSiteLevel (os.error: %s)@B" % exc
				return
			except:
				if TEST: print "(PVCS Custom Menu)@B@r<<<@x mergeSiteLevel (IOError)@B"
				return
	except os.error, exc:
		print "Removing of old menus file @B%@B failed ! Exception is 'os.error' and exception argument is '%s' !" % (location, exc)
		if TEST: print "(PVCS Custom Menu)@B@r<<<@x mergerSiteLevel (os.error: %s)@B" % exc
		return
	except:
		print "Removing of old menus file @B%@B failed ! Exception unknown !" % location
		if TEST: print "(PVCS Custom Menu)@B@r<<<@x mergeSiteLevel (IOError)@B"
		return
	if TEST: print "(PVCS Custom Menu)@B@r<<<@x mergeSiteLevel@B"
	return
	
# delete Pvcs Custom Menu, if available
def deletePvcsMenu():
	if TEST: print "(PVCS Custom Menu)@B@g>>>@x deletePvcsMenu@B"
	try:
		menuFile = open(location, "r")
		tempFileName = PVCSConstants.getTempFile()
		if TEST: print "(PVCS Custom Menu)\ttempFileName: '@B%s@B'" % tempFileName
		tempFile = open(tempFileName, "w")
		pvcsMenuFile = open(templateFile, "r")
	except IOError:
		if TEST: print "(PVCS Custom Menu)@B@r<<<@x deletePvcsMenu (IOError)@B"
		return
	# read the non-comment lines and store the lines in a list
	pvcsMenuFileLines = []
	for aPvcsMenuFileLine in pvcsMenuFile.readlines():
		if string.lstrip(aPvcsMenuFileLine) != "":
			pvcsMenuFileLines.append(aPvcsMenuFileLine)
	pvcsMenuFileLines.append("### automatic added menus START ###\n")
	pvcsMenuFileLines.append("### automatic added menus END ###\n")
	if TEST:
		print "(PVCS Custom Menu)@BpvcsMenuFile line list: @b",
		print pvcsMenuFileLines,
		print "@x@B"
	# read the UserMenus File
	lastLine = ""
	siteMenusMode = 0
	pvcsMenuMode = 0
	if TEST:
		print "(PVCS Custom Menu)@Bstart removing PvcsMenu lines from UserMenus@B"
	for aUserFileLine in menuFile.readlines():
		# copy only lines which ar not empty and not in PvcsMenu.sniff
		# NOTE: also comment lines from PvcsMenu.sniff will deleted
		if siteMenusMode == 0:
			if string.strip(aUserFileLine) == "### automatic merged Site Level menus START ###":
				siteMenusMode = 1
		else:
			if string.strip(aUserFileLine) == "### automatic merged Site Level menus END ###":
				siteMenusMode = 0
		
		# process the line only if we are not in siteMenusMode	
		if siteMenusMode == 1:
			if TEST:
				print "(PVCS Custom Menu)@B\twrite line !"
			# write to temporary file
			tempFile.write(aUserFileLine)
			# save to lastLine
			lastLine = string.lstrip(aUserFileLine)
			continue
		
		if pvcsMenuMode == 0:
			if string.strip(aUserFileLine) == "### automatic added menus START ###":
				pvcsMenuMode = 1
				continue
		else:
			if string.strip(aUserFileLine) == "### automatic added menus END ###":
				pvcsMenuMode = 0
				continue
		
		# process the line only if we are in pvcsMenuMode	
		if pvcsMenuMode == 0:
			if TEST:
				print "(PVCS Custom Menu)@B\twrite line !"
			# write to temporary file
			tempFile.write(aUserFileLine)
			# save to lastLine
			lastLine = string.lstrip(aUserFileLine)
			continue

		# do the following check to avoid to much empty lines
		if TEST:
			print "(PVCS Custom Menu)@Bcurrent UserMenus line: @b'%s'@x@B" % aUserFileLine
		if string.lstrip(aUserFileLine) != lastLine:
			# check, if it is a Pvcs Menu Line
			if aUserFileLine not in pvcsMenuFileLines:
				if TEST:
					print "(PVCS Custom Menu)@B\twrite line !"
				# write to temporary file
				tempFile.write(aUserFileLine)
				# save to lastLine
				lastLine = string.lstrip(aUserFileLine)
			else:
				if TEST:
					print "(PVCS Custom Menu)@B\tskip line ! (in pvcsMenuFileLines)"
		else:
			if TEST:
				print "(PVCS Custom Menu)@B\tskip line ! (is equal to lastLine)"
	# close all file
	menuFile.close()
	tempFile.close()
	pvcsMenuFile.close()
	# remove old file
	try:
		if sys.platform == "win32":
			chmod(location, 'ug+w')
		os.remove(location)
		# rename temp file
		if sys.platform == "win32":
			try:
				os.rename(tempFileName, location)
			except:
				# renaming failed
				print "Renaming from @B%s@B to @B%s@B failed ! Perform renaming manually to make the PVCS integration menus available !" % (tempFileName, location)
		else:
			try:
				menuFile = open(location, "w")
				tempFile = open(tempFileName, "r")
				menuFile.writelines(tempFile.readlines())
				tempFile.close()
				menuFile.close()
				os.remove(tempFileName)
			except os.error, exc:
				if TEST: print "(PVCS Custom Menu)@B@r<<<@x deletePvcsMenu (os.error: %s)@B" % exc
				return
			except:
				if TEST: print "(PVCS Custom Menu)@B@r<<<@x deletePvcsMenu (IOError)@B"
				return
	except os.error, exc:
		print "Removing of old menus file @B%@B failed ! Exception is 'os.error' and exception argument is '%s' !" % (location, exc)
		if TEST: print "(PVCS Custom Menu)@B@r<<<@x deletePvcsMenu (os.error: %s)@B" % exc
		return
	except:
		print "Removing of old menus file @B%@B failed ! Exception unknown !" % location
		if TEST: print "(PVCS Custom Menu)@B@r<<<@x deletePvcsMenu (IOError)@B"
		return
	if TEST: print "(PVCS Custom Menu)@B@r<<<@x deletePvcsMenu@B"
	return
	
# add Pvcs Custom Menu
def appendPvcsMenu():
	if TEST: print "(PVCS Custom Menu)@B@g>>>@x appendPvcsMenu@B"
	try:
		menuFile = open(location, "r")
		tempFileName = PVCSConstants.getTempFile()
		tempFile = open(tempFileName, "a")
		templFile = open(templateFile, "r")
		if TEST:
			print "(PVCS Custom Menu)@B\t",
			print menuFile
			print "(PVCS Custom Menu)@B\t",
			print tempFile
			print "(PVCS Custom Menu)@B\t",
			print templFile
	except IOError:
		if TEST: print "(PVCS Custom Menu)@B@r<<<@x appendPvcsMenu (IOError)@B"
		return
	# copy UserMenus File
	tempFile.writelines(menuFile.readlines())
	# insert for sure a empty Line
	tempFile.write("\n### automatic added menus START ###\n\n")
	# copy content of template file to menu file
	tempFile.writelines(templFile.readlines())
	tempFile.write("\n### automatic added menus END ###\n")
	# close all files
	menuFile.close()
	tempFile.close()
	templFile.close()
	# remove old UserMenus File
	try:
		if sys.platform == "win32":
			chmod(location, 'ug+w')
		os.remove(location)
		# rename temp file
		if sys.platform == "win32":
			try:
				os.rename(tempFileName, location)
			except:
				# renaming failed
				print "Renaming from @B%s@B to @B%s@B failed ! Perform renaming manually to make the PVCS integration menus available !" % (tempFileName, location)
		else:
			try:
				menuFile = open(location, "w")
				tempFile = open(tempFileName, "r")
				menuFile.writelines(tempFile.readlines())
				tempFile.close()
				menuFile.close()
				os.remove(tempFileName)
			except os.error, exc:
				if TEST: print "(PVCS Custom Menu)@B@r<<<@x appendPvcsMenu (os.error: %s)@B" % exc
				return
			except:
				if TEST: print "(PVCS Custom Menu)@B@r<<<@x appendPvcsMenu (IOError)@B"
				return
	except os.error, exc:
		print "Removing of old menus file @B%@B failed ! Exception is 'os.error' and exception argument is '%s' !" % (location, exc)
		if TEST: print "(PVCS Custom Menu)@B@r<<<@x appendPvcsMenu (os.error: %s)@B" % exc
		return
	except:
		print "Removing of old menus file @B%@B failed ! Exception unknown !" % location
		if TEST: print "(PVCS Custom Menu)@B@r<<<@x appendPvcsMenu (IOError)@B"
		return
	if TEST: print "(PVCS Custom Menu)@B@r<<<@x appendPvcsMenu@B"
	return


# start point
def start():
	if enableAutoMenu and doPreChecks() != -1:
		buildPVCSCustomMenu()
		
start()

